package cn.wen233.core;

import cn.wen233.basic.model.Instance;
import cn.wen233.basic.model.Namespace;
import cn.wen233.basic.model.NodeRecord;
import cn.wen233.basic.model.Service;
import cn.wen233.core.filter.InstanceFilter;
import cn.wen233.core.filter.ServiceFilter;
import cn.wen233.core.page.PageIn;
import cn.wen233.core.page.PageOut;
import cn.wen233.core.service.InstanceService;
import cn.wen233.core.service.NamespaceService;
import cn.wen233.core.service.NodeRecordService;
import cn.wen233.core.service.ServiceService;
import cn.wen233.core.service.impl.PersistenceInstanceServiceImpl;
import cn.wen233.core.service.impl.PersistenceNamespaceServiceImpl;
import cn.wen233.core.service.impl.PersistenceNodeRecordServiceImpl;
import cn.wen233.core.service.impl.PersistenceServiceServiceImpl;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 服务管理
 *
 * @author wenei
 * @date 2021-10-11 10:49
 */
@Component
public class ServiceManager implements ApplicationRunner {

    @Resource(type = PersistenceNamespaceServiceImpl.class)
    private NamespaceService namespaceService;

    @Resource(type = PersistenceServiceServiceImpl.class)
    private ServiceService serviceService;

    @Resource(type = PersistenceInstanceServiceImpl.class)
    private InstanceService instanceService;

    @Resource(type = PersistenceNodeRecordServiceImpl.class)
    private NodeRecordService nodeRecordService;

    private static final ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1);


    public void createNamespace(String namespaceId, String namespaceName, String description) {
        namespaceService.createNamespace(namespaceId, namespaceName, description);
    }

    public List<Namespace> getAllNamespace() {
        return namespaceService.getAll();
    }

    public Namespace findNamespace(String namespaceId) {
        return namespaceService.findByNamespaceId(namespaceId);
    }

    public void updateNamespace(String namespaceId, String namespaceName, String description) {
        namespaceService.updateNamespace(namespaceId, namespaceName, description);
    }

    public void deleteNamespace(String namespaceId) {
        namespaceService.deleteNamespace(namespaceId);
    }

    public List<Service> getAllService(String namespaceId) {
        return serviceService.findAll(namespaceId);
    }

    public PageOut<Service> findPageService(ServiceFilter filter) {
        return serviceService.findPage(filter);
    }

    public Service getByNamespaceAndGroupAndServiceName(String namespaceId, String group, String serviceName) {
        return serviceService.findBy(namespaceId, group, serviceName);
    }

    public void createService(String name, String appName, String groupName, String namespaceId) {
        Service service = new Service();
        service.setName(name);
        service.setAppName(appName);
        service.setGroupName(groupName);
        service.setNamespaceId(namespaceId);
        serviceService.create(service);
    }

    public void updateService(String id, String name, String appName, String groupName) {
        Service service = new Service();
        service.setName(name);
        service.setAppName(appName);
        service.setGroupName(groupName);
        serviceService.update(id, service);
    }

    public void deleteService(String id) {
        serviceService.delete(id);
    }

    public List<Instance> getAllInstance(String namespaceId, String serviceId) {
        return instanceService.getServiceInstance(namespaceId, serviceId);
    }

    public void instanceHeartbeat(String instanceId) {
        instanceService.heartbeat(instanceId);
    }

    public PageOut<Instance> findPageInstance(InstanceFilter filter) {
        return instanceService.findPage(filter);
    }

    public Instance registerInstance(String namespaceId, String serviceId, String host, int port) {
        return instanceService.registerInstance(namespaceId, serviceId, host, port);
    }

    public void removeInstance(String namespaceId, String serviceId, String id) {
        instanceService.removeInstance(namespaceId, serviceId, id);
    }


    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 遍历所有的服务，当其没有节点30s时自动删除
        threadPool.scheduleAtFixedRate(() -> {
            List<Namespace> allNamespace = getAllNamespace();
            allNamespace.forEach(namespace -> {
                List<Service> allService = getAllService(namespace.getNamespaceId());
                allService.forEach(service -> {
                    List<Instance> allInstance = getAllInstance(namespace.getNamespaceId(), service.getId());
                    if (allInstance == null || allService.size() == 0) {
                        deleteService(service.getId());
                    }
                });
            });
        }, 60, 60, TimeUnit.SECONDS);
    }
}
